#include "../../mqServer/virtual_host.hpp"
#include <gtest/gtest.h>

using namespace mq;

int n = 3;     // 测试规模：交换机/队列/绑定数量
int m = 10010; // 消息数量

class VirtualHostTest : public testing::Test // 独立测试套件
{
public:
    void SetUp() override
    {
        // cout << "单元测试前执行环境初始化" << endl;
        // 0.构造虚拟机对象
        host = make_shared<VirtualHost>("host", "./virtual/host", "host.db");
        // 1.声明交换机和队列
        Map map;
        for (int i = 1; i <= n; i++)
        {
            host->declareExchange("exchange" + to_string(i), DIRECT, true, true, map);
            host->declareMsgQueue("queue" + to_string(i), true, true, true, map);
        }
        // 2.添加绑定
        for (int i = 1; i <= n; i++)
        {
            string ename = "exchange" + to_string(i);
            for (int j = 1; j <= n; j++)
            {
                string qname = "queue" + to_string(j);
                host->Bind(ename, qname, ename + "&" + qname);
            }
        }
        // 3.发布消息
        for (int i = 1; i <= n; i++)
        {
            string qname = "queue" + to_string(i);
            for (int j = 1; j <= m; j++)
            {
                host->basicPublish(qname, nullptr, "hello world " + to_string(j));
            }
        }
    }
    void TearDown() override
    {
        // cout << "单元测试后执行环境清理" << endl;
        host->clear();
    }

    host_ptr host;
};

TEST_F(VirtualHostTest, init_test) // 初始化测试和历史数据恢复测试
{
    // 1.判断所有交换机和队列都需要存在
    for (int i = 1; i <= n; i++)
    {
        ASSERT_EQ(host->existExchange("exchange" + to_string(i)), true);
        ASSERT_EQ(host->existMsgQueue("queue" + to_string(i)), true);
    }
    // 2.判断所有绑定都需要存在
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            ASSERT_EQ(host->existBinding("exchange" + to_string(i), "queue" + to_string(i)), true);
        }
    }
}

TEST_F(VirtualHostTest, front_ack_test) // 获取推送消息测试和确认删除消息，垃圾回收测试
{
    for (int i = 1; i <= n; i++)
    {
        string qname = "queue" + to_string(i);
        for (int j = 1; j <= m; j++)
        {
            m_ptr msgp = host->basicConsume(qname); // 获取队首消息
            ASSERT_NE(msgp, m_ptr());
            ASSERT_EQ(msgp->payload().body(), "hello world " + to_string(j));
            if (j % 2 == 1)
                host->basicAck(qname, msgp->payload().properties().id()); // 确认删除消息
        }
        m_ptr msgp = host->basicConsume(qname); // 再次获取为空
        ASSERT_EQ(msgp, m_ptr());
    }
}

TEST_F(VirtualHostTest, remove_exchange_test) // 删除交换机测试
{
    for (int i = 1; i <= n; i++)
    {
        string ename = "exchange" + to_string(i);
        host->deleteExchange(ename);
        ASSERT_EQ(host->existExchange(ename), false);
        for (int j = 0; j <= n; j++)
        {
            string qname = "queue" + to_string(j);
            ASSERT_EQ(host->existBinding(ename, qname), false);
        }
    }
}

TEST_F(VirtualHostTest, remove_queue_test) // 删除交换机测试
{
    for (int i = 1; i <= n; i++)
    {
        string qname = "queue" + to_string(i);
        host->deleteMsgQueue(qname);
        ASSERT_EQ(host->existMsgQueue(qname), false);
        for (int j = 0; j <= n; j++)
        {
            string ename = "exchange" + to_string(j);
            ASSERT_EQ(host->existBinding(ename, qname), false);
        }
        host->basicPublish(qname, nullptr, "abc"); // 查找不到队列
    }
}

TEST_F(VirtualHostTest, get_exchange_bindings_test) // 获取交换机绑定的所有队列
{
    for (int i = 1; i <= n; i++)
    {
        string ename = "exchange" + to_string(i);
        MsgQueueBindingMap mqbp = host->getExchangeBindings(ename);
        for (int j = 1; j <= n; j++)
        {
            string qname = "queue" + to_string(j);
            b_ptr bind = mqbp[qname];
            ASSERT_EQ(bind->_ename, ename);
            ASSERT_EQ(bind->_qname, qname);
        }
    }
}

int main(int argc, char *argv[])
{
    testing::InitGoogleTest(&argc, argv);
    RUN_ALL_TESTS();
    return 0;
}